#include "SelectionFactory.h"
#include "Random/RandomSelection.h"
#include "Rank/RankSelection.h"
#include "Roulette/RouletteSelection.h"
#include "Tournament/TournamentSelection.h"
#include "../Exception/GA_Exception.h"

SelectionFactory::SelectionFactory() {
}

Selection* SelectionFactory::generateSelection() {
    //TODO: In the future, we should
    //look at ways of dynamically discovering which selection methods are available on
    //the system, and loading them up.  Also, we should look at dynamically querying
    //a selection about what options / solutions / whatever it supports.
    
    cout << "Which of the following selections do you wish to use?" << endl;
    cout << RANDOM_SELECTION << ") Random Selection" << endl;
    cout << RANK_SELECTION << ") Rank Selection" << endl;
    cout << ROULETTE_SELECTION << ") Roulette Selection" << endl;
    cout << TOURNAMENT_SELECTION << ") Tournament Selection" << endl;
    int answer;
        
    while (true) 
    {
        cout << "? ";
        cin >> answer;
        
        try
        {
            return generateSelection(answer);
        }
        catch (exception &e)
        {
            cout << "Invalid selection." << endl;
        }
    }
}

Selection* SelectionFactory::generateSelection(int selectionType) {
    switch (selectionType)
    {
        case RANDOM_SELECTION:
        {
            return RandomSelection::getSelection();
            break;
        }
        case RANK_SELECTION:
        {
            return RankSelection::getSelection();
            break;
        }
        case ROULETTE_SELECTION:
        {
            return RouletteSelection::getSelection();
            break;
        }
        case TOURNAMENT_SELECTION:
        {
            unsigned int tournamentSize;
            cout << "What tournament size do you want?  ( >= 2 )" << endl;
            cin >> tournamentSize;
            return TournamentSelection::getSelection(tournamentSize);
            break;
        }
        default:
        {
            throw Unsupported_selection_exception();
            break;
        }
    }
}
